import React, { Component } from "react";

class Theory extends Component {
    render() {
        return (
            <>
                <div className="outer" id="outer"
                    onClickCapture={() => {
                        console.log('outer-捕获--合成');
                    }}
                    onClick={() => {
                        console.log('outer-冒泡--合成');
                    }}
                >
                    <div className="inner" id="inner"
                        onClickCapture={() => {
                            console.log('inner-捕获--合成');
                        }}
                        onClick={(ev) => {
                            // ev.stopPropagation(); // 阻止 原生&合成 事件传播
                            // document捕获
                            // body捕获
                            // outer-捕获--合成
                            // inner-捕获--合成
                            // root捕获
                            // outer捕获--原生
                            // inner捕获--原生
                            // inner冒泡--原生
                            // outer冒泡--原生
                            // inner-冒泡--合成
                            // root冒泡

                            // ev.nativeEvent.stopPropagation(); // 只阻止原生 事件传播
                            // document捕获
                            // body捕获
                            // outer-捕获--合成
                            // inner-捕获--合成
                            // root捕获
                            // outer捕获--原生
                            // inner捕获--原生
                            // inner冒泡--原生
                            // outer冒泡--原生
                            // inner-冒泡--合成
                            // outer-冒泡--合成
                            // root冒泡

                            ev.nativeEvent.stopImmediatePropagation(); // 原生事件对象的阻止事件传播，只不过 还可以阻止#root方法执行
                            // document捕获
                            // body捕获
                            // outer-捕获--合成
                            // inner-捕获--合成
                            // root捕获
                            // outer捕获--原生
                            // inner捕获--原生
                            // inner冒泡--原生
                            // outer冒泡--原生
                            // inner-冒泡--合成
                            // outer-冒泡--合成
                            console.log('inner-冒泡--合成');
                        }}
                    ></div>
                </div>
            </>
        )
    };
    componentDidMount() {
        // document
        document.addEventListener('click', () => {
            console.log('document捕获');
        }, true);
        document.addEventListener('click', () => {
            console.log('document冒泡');
        }, false);

        // body
        document.body.addEventListener('click', () => {
            console.log('body捕获');
        }, true);
        document.body.addEventListener('click', () => {
            console.log('body冒泡');
        }, false);

        // root
        const rootDom = document.querySelector('#root');
        rootDom.addEventListener('click', () => {
            console.log('root捕获');
        }, true);
        rootDom.addEventListener('click', () => {
            console.log('root冒泡');
        }, false);

        // outer
        const outerDom = document.querySelector('#outer');
        outerDom.addEventListener('click', () => {
            console.log('outer捕获--原生');
        }, true);
        outerDom.addEventListener('click', () => {
            console.log('outer冒泡--原生');
        }, false);

        // inner
        const innerDom = document.querySelector('#inner');
        innerDom.addEventListener('click', () => {
            console.log('inner捕获--原生');
        }, true);
        innerDom.addEventListener('click', () => {
            console.log('inner冒泡--原生');
        }, false);
    };
};

export default Theory;
/*
    React 合成事件处理原理
        绝对不是给当前元素基于addEventListener做的单独事件绑定，React中的合成事件都是基于事件委托处理的；
            +在React17及以后版本都是委托给#root这个容器【捕获 冒泡阶段都做了委托】；
            +但是在React17之前，都是委托给document这个容器，而且只做了冒泡阶段的委托；
            +对于没有实现事件传播机制的事件，才是做的单独事件绑定，【例如：mouseEnter,mouseLeave】
            
            《React17---》
            在组件渲染的时候，如果发现jsx元素中有onXXX/onXXXCapture这样的属性，不会给当前元素直接做事件绑定，只是把绑定的方法赋值
            给元素的相关属性；例如: 
                inner.onClick = () => {}
                inner.onClickCapture = () => {}
                outer.onClick = () => {}
                outer.onClickCapture = () => {}
            
            然后对#root这个容器做了事件绑定（捕获和冒泡都做了）；
                因为组件中的所渲染的内容，最后都会插入到#root容器中，这样，点击页面中任何一个元素，最后都会将#root的点击行为触发;
                而在给#root绑定的方法中，把之前给元素设置的onClick/onClickCapture属性，在相应的阶段执行；

                document捕获--原生事件绑定                                            
                document冒泡--原生事件绑定
                body捕获--原生事件绑定
                body冒泡--原生事件绑定
                root捕获--原生事件绑定                                                          
                root冒泡--原生事件绑定
            <React内部绑定>
            root捕获--（内部）原生事件绑定
            root冒泡--（内部）原生事件绑定
                outer捕获--原生事件绑定
                outer冒泡--原生事件绑定
                inner捕获--原生事件绑定
                inner冒泡--原生事件绑定
            <-------------------------------------->
                outer捕获--合成事件绑定 outer.onClickCapture = () => {}
                outer冒泡--合成事件绑定 outer.onClick = () => {}
                inner捕获--合成事件绑定 inner.onClickCapture = () => {}
                inner冒泡--合成事件绑定 inner.onClick = () => {}

                点击inner后    ===》
                window捕获    ===》
                document捕获     ===》  <1> "document捕获"
                html捕获    ===》
                body捕获    ===》   <2> "body捕获"
                root捕获    ===》   root内置（window.onClickCapture ... root.onClickCapture outer.onClickCapture inner.onClickCapture）
                                   <3> "outer捕获【合成】"  ===》   <4> "inner捕获【合成】"   ===>    <5> "root捕获"

                outer捕获    ===》  <6> "outer捕获"
                inner捕获    ===》  <7> "inner捕获"
                inner冒泡    ===》  <8> "inner冒泡"
                outer冒泡    ===》  <9> "outer冒泡"
                root冒泡    ===》   root内置（inner.onClick outer.onClick root.onClick ... window.onClick）
                                   <10> "inner冒泡【合成】"    ===》   <11> "outer冒泡【合成】"   ===》   <12> "root冒泡"
                                   
                body冒泡    ===》   <13> "body冒泡"
                html冒泡    ===》
                document冒泡    ===》   <14> "document冒泡"   
                window冒泡    ===》
            
            《React16》
            在16版本中，合成事件的处理机制，不是将事件委托给#root容器，而是委托给document，并且只做了冒泡阶段的委托，在委托的方法中，将
            onClick onClickCapture属性的方法执行；
            ev.persist(); 可以将合成事件对象中的信息保留下来 
*/